/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.ui.popup;

import com.daikit.commons.shared.bean.DkConnectionData;
import com.daikit.commons.shared.bean.DkLanguage;
import com.daikit.daikit4gxt.client.DkBaseMain;
import com.daikit.daikit4gxt.client.action.DkBaseAction;
import com.daikit.daikit4gxt.client.log.DkLogger;
import com.daikit.daikit4gxt.client.ui.editor.field.DkLanguageChooserComboBox;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.ui.InlineLabel;
import com.sencha.gxt.cell.core.client.form.PasswordInputCell;
import com.sencha.gxt.cell.core.client.form.TextInputCell;
import com.sencha.gxt.core.client.util.Margins;
import com.sencha.gxt.widget.core.client.Dialog;
import com.sencha.gxt.widget.core.client.box.AlertMessageBox;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.BoxLayoutContainer.BoxLayoutPack;
import com.sencha.gxt.widget.core.client.container.HorizontalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.HorizontalLayoutContainer.HorizontalLayoutData;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData;
import com.sencha.gxt.widget.core.client.form.FieldLabel;
import com.sencha.gxt.widget.core.client.form.PasswordField;
import com.sencha.gxt.widget.core.client.form.TextField;
import com.sencha.gxt.widget.core.client.form.validator.EmptyValidator;


/**
 * The connection popup.
 * 
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 */
public class DkConnectionPopup
{

	protected DkLogger log = DkLogger.getLog(DkConnectionPopup.class);

	protected static DkConnectionPopup instance;

	protected final int labelWidth = 80;

	/**
	 * Return an instance of {@link DkConnectionPopup}
	 * 
	 * @return an instance of {@link DkConnectionPopup}
	 */
	public static DkConnectionPopup instance()
	{
		if (instance == null)
		{
			instance = new DkConnectionPopup();
			instance.initialize();
		}
		return instance;
	}

	protected AbstractDkDialog dialogBox;
	protected VerticalLayoutContainer verticalLayoutContainer;
	protected TextField loginTextField;
	protected PasswordField passwordTextField;
	protected FieldLabel loginFieldLabel;
	protected FieldLabel passwordFieldLabel;
	protected DkLanguageChooserComboBox languageCombobox;
	protected FieldLabel languageFieldLabel;

	protected final int WIDTH_WITHOUT_PASSWORD = 400;
	protected final int WIDTH_WITH_PASSWORD = 550;

	protected DkBaseAction<?> chainActionIfLoginSucceded = null;

	protected DkConnectionPopup()
	{
		// Nothing done here
	}

	protected void initialize()
	{
		createDialog();
		createVerticalLayoutContainer();
		createLoginTextField();
		createPasswordTextField();
		createLanguageCombobox();
		addFieldsInLayout();
	}

	protected void createDialog()
	{
		dialogBox = new AbstractDkDialog()
		{
			@Override
			protected void onButtonPressed(final TextButton button)
			{
				if (button == getButtonBar().getItemByItemId(PredefinedButton.OK.name()))
				{
					onSubmit();
				}
				else if (button == getButtonBar().getItemByItemId(PredefinedButton.CANCEL.name()))
				{
					onCancel();
				}
				super.onButtonPressed(button);
			}
		};
		dialogBox.setModal(true);
		// dialogBox.setIcon(null);
		dialogBox.setHeadingText(DkBaseMain.i18n().connection_popup_title(DkBaseMain.i18n().appTitle()));
		dialogBox.setPredefinedButtons(Dialog.PredefinedButton.OK, Dialog.PredefinedButton.CANCEL);
		dialogBox.setButtonAlign(BoxLayoutPack.CENTER);
	}

	protected void createVerticalLayoutContainer()
	{
		verticalLayoutContainer = new VerticalLayoutContainer();
		verticalLayoutContainer.getElement().getStyle().setProperty("textAlign", "center");
		verticalLayoutContainer.getElement().getStyle().setPaddingTop(3, Unit.PX);

		final String connectionMessage = DkBaseMain.controller().getConnectionPopupMessage();
		if (connectionMessage != null)
		{
			final InlineLabel text = new InlineLabel(connectionMessage);
			// ("font-weight", "bold");
			final VerticalLayoutData varticalLayoutData = new VerticalLayoutData(1, -1);
			varticalLayoutData.setMargins(new Margins(5, 0, 10, 0));
			verticalLayoutContainer.add(text, varticalLayoutData);
		}
		dialogBox.add(verticalLayoutContainer);
	}

	protected void createLoginTextField()
	{
		loginTextField = new TextField(new TextInputCell()
		{
			@Override
			protected void onEnterKeyDown(final com.google.gwt.cell.client.Cell.Context context, final Element parent,
					final String value, final NativeEvent event, final ValueUpdater<String> valueUpdater)
			{
				super.onEnterKeyDown(context, parent, value, event, valueUpdater);
				onSubmit();
			}
		});
		loginFieldLabel = new FieldLabel(loginTextField, DkBaseMain.i18n().connection_popup_login_label());
		loginFieldLabel.setLabelWidth(labelWidth);

		loginTextField.addValidator(new EmptyValidator<String>());
	}

	protected void createPasswordTextField()
	{
		passwordTextField = new PasswordField(new PasswordInputCell()
		{
			@Override
			protected void onEnterKeyDown(final com.google.gwt.cell.client.Cell.Context context, final Element parent,
					final String value, final NativeEvent event, final ValueUpdater<String> valueUpdater)
			{
				super.onEnterKeyDown(context, parent, value, event, valueUpdater);
				onSubmit();
			}
		});
		passwordFieldLabel = new FieldLabel(passwordTextField, DkBaseMain.i18n().connection_popup_password_label());
		passwordFieldLabel.setLabelWidth(labelWidth);

		passwordTextField.addValidator(new EmptyValidator<String>());
	}


	private void createLanguageCombobox()
	{
		if (DkBaseMain.config().isMultiLanguageApplication())
		{
			languageCombobox = new DkLanguageChooserComboBox(false, DkBaseMain.model().getAvailableLanguages());
			languageCombobox.addValidator(new EmptyValidator<DkLanguage>());

			languageFieldLabel = new FieldLabel(languageCombobox, DkBaseMain.i18n().connection_popup_language_label());
			languageFieldLabel.setLabelWidth(labelWidth);
		}

	}

	protected void addFieldsInLayout()
	{
		if (DkBaseMain.config().isConnectionNeedingPassword())
		{
			if (DkBaseMain.config().isMultiLanguageApplication())
			{
				verticalLayoutContainer.add(loginFieldLabel, new VerticalLayoutData(1, -1));
				verticalLayoutContainer.add(passwordFieldLabel, new VerticalLayoutData(1, -1));
				verticalLayoutContainer.add(languageFieldLabel, new VerticalLayoutData(1, -1));
			}
			else
			{
				dialogBox.setWidth(WIDTH_WITH_PASSWORD);
				final HorizontalLayoutContainer horizontalLayoutContainer = new HorizontalLayoutContainer();
				verticalLayoutContainer.add(horizontalLayoutContainer);

				final HorizontalLayoutData leftData = new HorizontalLayoutData(0.5, 1);
				final VerticalLayoutContainer left = new VerticalLayoutContainer();
				horizontalLayoutContainer.add(left, leftData);

				final HorizontalLayoutData rightData = new HorizontalLayoutData(0.5, 1);
				final VerticalLayoutContainer right = new VerticalLayoutContainer();
				horizontalLayoutContainer.add(right, rightData);

				left.add(loginFieldLabel);
				right.add(passwordFieldLabel);
			}
		}
		else
		{
			dialogBox.setWidth(WIDTH_WITHOUT_PASSWORD);
			verticalLayoutContainer.add(loginFieldLabel);
		}
	}

	protected void onCancel()
	{
		dialogBox.hide();
	}

	protected void onSubmit()
	{
		validate();
		final String login = loginTextField.getValue();
		final String password = DkBaseMain.config().isConnectionNeedingPassword() ? passwordTextField.getValue() : null;
		final DkLanguage language = DkBaseMain.config().isMultiLanguageApplication() ? languageCombobox.getValue() : null;
		if (DkBaseMain.config().isMultiLanguageApplication() && !languageCombobox.isValid() || !loginTextField.isValid()
				|| DkBaseMain.config().isConnectionNeedingPassword() && !passwordTextField.isValid())
		{
			showInvalidMessageBox();
		}
		else
		{
			final DkConnectionData connectionData = createConnectionData(login, password, language);
			DkBaseMain.controller().doConnect(connectionData, chainActionIfLoginSucceded);
			dialogBox.hide();
		}
	}

	protected DkConnectionData createConnectionData(final String login, final String password, final DkLanguage language)
	{
		final DkConnectionData connectionData = new DkConnectionData();
		connectionData.setLogin(login);
		connectionData.setPassword(password);
		connectionData.setLanguage(language);
		return connectionData;
	}

	protected void validate()
	{
		loginTextField.validate();
		passwordTextField.validate();
		if (DkBaseMain.config().isMultiLanguageApplication())
		{
			languageCombobox.validate();
		}
	}

	/**
	 * Show the Dialog box without a chain action if user login succeeded
	 */
	public void show()
	{
		loginTextField.clearInvalid();
		passwordTextField.clearInvalid();
		loginTextField.focus();
		if (DkBaseMain.config().isMultiLanguageApplication())
		{
			languageCombobox.clearInvalid();
			if (languageCombobox.getValue() == null)
			{
				languageCombobox.setValue(DkBaseMain.model().getCurrentLanguage(), false);
			}
		}
		show(null);
	}

	protected void showInvalidMessageBox()
	{
		new AlertMessageBox(DkBaseMain.i18n().connection_popup_bad_information_popup_title(), DkBaseMain.i18n()
				.connection_popup_bad_information_popup_correct_fields()).show();
	}

	/**
	 * Show the Dialog box with a chain action if the user login succeeded
	 * 
	 * @param chainActionIfLoginSucceded
	 *           the chain action
	 */
	public void show(final DkBaseAction<?> chainActionIfLoginSucceded)
	{
		this.chainActionIfLoginSucceded = chainActionIfLoginSucceded;
		dialogBox.show();
	}

}
